﻿// Cow Exhibition POJ - 2184.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;
//https://vjudge.csgrandeur.cn/problem/POJ-2184


/*
奶牛们想向公众证明，它们既聪明又有趣。为此，贝西组织了一次奶牛展览。
她对 N (1 <= N <= 100) 头奶牛进行了一次全面的访谈，并为每头牛确定了两个值：
奶牛的聪明度 Si (-1000 <= Si <= 1000) 和奶牛的有趣度 Fi (-1000 <= Fi <= 1000)。

贝西必须选择哪些奶牛参加展览。她认为，牛群的总聪明度 TS 是 Si 的总和，
同样，牛群的总有趣度 TF 是 Fi 的总和。
Bessie 希望最大化 TS 和 TF 的总和，但她也希望这两个值都不是负数
（因为她还必须证明奶牛们是全面发展的；负的 TS 或 TF 会破坏这一点）。
帮助 Bessie 最大化 TS 和 TF 的总和，同时不让这两个值中的任何一个变成负数。
输入
* 第 1 行： 一个整数 N，即奶牛的数量

* 第 2...N+1 行：两个空格分隔的整数 Si 和 Fi，分别表示每头奶牛的聪明度和有趣度。
输出
* 第 1 行： 一个整数：TS 和 TF 的最优和，且 TS 和 TF 均为非负。
如果没有奶牛子集的 TS 和 TF 均为非负，则打印 0。

5
-5 7
8 -6
6 -3
2 1
-8 -5

8
*/

const int N = 200010;
int dp[2][N];
int n;

int S[N];
int F[N];

void solve() {
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < N; j++) {
			dp[i][j] = -99999999;
		}
	}
	int base = N/2;
	dp[0][base] = 0;
	int curr = 1;
	int prev = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < N; j++) {
			dp[curr][j] = dp[prev][j];
			if (j - S[i] >=0 && j-S[i] <N) {
			//if (j - S[i] >= 0 ) {		//坑点 上下限都要判断
				dp[curr][j] = max(dp[curr][j], dp[prev][j - S[i]] + F[i]);
			}
			if (dp[curr][j] >= -99999999 / 2) {
				//cout << "i = " << i << ". j = " << j << ". dp = " << dp[curr][j] << endl;
			}
		}
		swap(curr, prev);
	}

	int ans = 0;
	for (int i = base; i < N; i++) {
		if(dp[prev][i] >= 0)
			ans = max(ans, dp[prev][i] +i -base);
	}

	cout << ans << endl;
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> S[i] >> F[i];
	}
	solve();

	return 0;
}
